<?
/**
 * 字符加密处理类
 * @author 邝达峰
 */
class carry
{
	function carry($n,$m)
	{
		$this->n=$n;
		$this->m=$m;
		$this->chn['0']=0;
		$this->chn['1']=1;
		$this->chn['2']=2;
		$this->chn['3']=3;
		$this->chn['4']=4;
		$this->chn['5']=5;
		$this->chn['6']=6;
		$this->chn['7']=7;
		$this->chn['8']=8;
		$this->chn['9']=9;
		$this->chn['A']=10;
		$this->chn['B']=11;
		$this->chn['C']=12;
		$this->chn['D']=13;
		$this->chn['E']=14;
		$this->chn['F']=15;
		$this->chn['G']=16;
		$this->chn['H']=17;
		$this->chn['I']=18;
		$this->chn['J']=19;
		$this->chn['K']=20;
		$this->chn['L']=21;
		$this->chn['M']=22;
		$this->chn['N']=23;
		$this->chn['O']=24;
		$this->chn['P']=25;
		$this->chn['Q']=26;
		$this->chn['R']=27;
		$this->chn['S']=28;
		$this->chn['T']=29;
		$this->chn['U']=30;
		$this->chn['V']=31;
		$this->chn['W']=32;
		$this->chn['X']=33;
		$this->chn['Y']=34;
		$this->chn['Z']=35;
		$this->cn[0]='0';
		$this->cn[1]='1';
		$this->cn[2]='2';
		$this->cn[3]='3';
		$this->cn[4]='4';
		$this->cn[5]='5';
		$this->cn[6]='6';
		$this->cn[7]='7';
		$this->cn[8]='8';
		$this->cn[9]='9';
		$this->cn[10]='A';
		$this->cn[11]='B';
		$this->cn[12]='C';
		$this->cn[13]='D';
		$this->cn[14]='E';
		$this->cn[15]='F';
		$this->cn[16]='G';
		$this->cn[17]='H';
		$this->cn[18]='I';
		$this->cn[19]='J';
		$this->cn[20]='K';
		$this->cn[21]='L';
		$this->cn[22]='M';
		$this->cn[23]='N';
		$this->cn[24]='O';
		$this->cn[25]='P';
		$this->cn[26]='Q';
		$this->cn[27]='R';
		$this->cn[28]='S';
		$this->cn[29]='T';
		$this->cn[30]='U';
		$this->cn[31]='V';
		$this->cn[32]='W';
		$this->cn[33]='X';
		$this->cn[34]='Y';
		$this->cn[35]='Z';
	}

	function check1($a)
	{
		if(preg_match("/[0-9]/",$a))
		if($a>=2)
		if($a<=36)
		return true;
		return false;
	}

	function check2($a)
	{
		$la=0;
		for($j=0;$j<strlen($a);$j++){
			if($this->chn[substr($a,$j,1)]>=$this->n){
				$la=1;
			}
			if($la){
				break;
			}
		}
		if($la){
			return false;
		}
		else{
			return true;
		}
	}
	function toDEC($a)//$n->十进制
	{
		if($this->n==10)
		return $a;
		else
		{
			$a=strrev($a);
			$k=0;
			for($i=0;$i<strlen($a);$i++)
			{
				$k+=$this->chn[substr($a,$i,1)]*pow($this->n,$i);
			}
			return $k;
		}
	}
	function gethigh($a)
	{
		if($a<=1)
		return 1;
		else
		{
			for($i=0;$i<100;$i++)
			{
				if(pow($this->m,$i)>$a)
				break;
			}
			return $i;
		}
	}
	function toM($a)
	{
		$a1=$this->gethigh($a);
		$res="";
		for($i=1;$i<=$a1;$i++)
		{
			$u=($a-$a%pow($this->m,($a1-$i)))/(pow($this->m,($a1-$i)));
			$a-=$u*pow($this->m,($a1-$i));
			$res.=$this->cn[$u];
		}
		return $res;
	}
	function get($a)
	{
		if(!$this->n)$this->n=10;
		if(!$this->m)$this->m=10;
		if(($this->check1($this->n))&&($this->check1($this->m)))
		{
			if(preg_match('/[0-9A-Z]/',$a))
			{
				if($this->check2($a))
				{
					return $this->toM($this->toDEC($a));
				}
				else
				return false;
			}
			else
			return false;
		}
		else
		return false;
	}
}

/**
 * 字符加密基类
 */
class Crypt
{
	function Crypt()
	{
		for($i=0;$i<10;$i++){
			$this->hu1[$i]=$i;
			$this->hu2[$i]=$i;
		}
		for($i=10;$i<36;$i++){
			$this->hu1[$i]=chr($i+55);
			$this->hu2[chr($i+55)]=$i;
		}
		for($i=36;$i<62;$i++){
			$this->hu1[$i]=chr($i+61);
			$this->hu2[chr($i+61)]=$i;
		}
		$this->hu1[62]=chr(42);
		$this->hu1[63]=chr(43);
		$this->hu2[chr(42)]=62;
		$this->hu2[chr(43)]=63;
	}

	/**
	 * 将一组字符转变成为代码0~65536
	 * @param  $str 需要处理的字符
	 * @return string
	 */
	function tocode($str)
	{
		$huyang1=new carry(10,33);
		$j=0;
		for($i=0;$i<strlen($str);$i++){
			$p=ord(substr($str,$i,1));
			if($p>160){
				$q=ord(substr($str,++$i,1));
				$p=$p*256+$q;
			}
			else{
				$p=255*256+$p;
			}
			$ret.=$huyang1->get($p);
			$j++;
		}
		return $ret;
	}

	/**
	 * 获取到字符编码
  	* @param  $str 需要处理的字符
	 * @return string
	 */
	function getcode($str)
	{
		$huyang=new carry(33,10);
		$res="";
		for($i=0;$i<(strlen($str)/4);$i++){
			$a=$huyang->get(substr($str,($i*4),4));
			$a2=$a%256;
			$a1=($a-$a2)/256;
			if($a >= 1985 && $a <= 2010){
				$res .= chr($a-1920);
			}
			else{
				if($a1==255){
					$res.=chr($a2);
				}
				else{
					$res.=chr($a1).chr($a2);
				}
			}
		}
		return $res;
	}

	/**
	 * 字符加密
	 * @param  $str 需要加密的字符
	 * @return string
	 */
	function encode($str){
		$res="";
		$huyang=new carry(35,7);
		$huyang1=new carry(8,10);
		$str1=$this->tocode($str);
		$k=ceil(strlen($str1)/3);
		for($i=0;$i<$k;$i++){
			$word=$this->hu1[rand(0,61)];
			$res1=$huyang1->get($huyang->get(substr($str1,($i*3),3)));
			$res11=($res1-$res1%(64*64))/(64*64);
			$res1-=$res11*64*64;
			$res12=($res1-$res1%64)/64;
			$res1-=$res12*64;
			$res13=$res1;
			if($i==($k-1)){
				if($res11!=0){
					$res.=$this->hu1[$res11].$this->hu1[$res12].$this->hu1[$res13].$word;
				}
				elseif($res12!=0){
					$res.=$this->hu1[$res12].$this->hu1[$res13].$word;
				}
				elseif($res13!=0){
					$res.=$this->hu1[$res13].$word;
				}
			}
			else{
				$res.=$this->hu1[$res11].$this->hu1[$res12].$this->hu1[$res13].$word;
			}
		}
		return trim($res);
	}

	function discode($str)
	{
		$len=ceil(strlen($str)/4);
		$res="";
		$a=strlen($str)-4*($len-1);
		for($i=0;$i<$len;$i++)
		{
			if($i!=($len-1)){
				$res1=substr($str,$i*4,1);
				$res2=substr($str,($i*4+1),1);
				$res3=substr($str,($i*4+2),1);
				$res11=$this->hu2[$res1];
				$res12=$this->hu2[$res2];
				$res13=$this->hu2[$res3];
				$res14=$res11*64*64+$res12*64+$res13;
				$res.=" ".$res14;
			}
			else{
				if($a%4==0){
					$res1=substr($str,$i*4,1);
					$res2=substr($str,($i*4+1),1);
					$res3=substr($str,($i*4+2),1);
					$res11=$this->hu2[$res1];
					$res12=$this->hu2[$res2];
					$res13=$this->hu2[$res3];
					$res14=$res11*64*64+$res12*64+$res13;
					$res.=" ".$res14;
				}
				elseif($a%4==2){
					$res1=substr($str,$i*4,1);
					$res11=$this->hu2[$res1];
					$res14=$res11;
					$res.=" ".$res14;
				}
				elseif($a%4==3){
					$res1=substr($str,$i*4,1);
					$res2=substr($str,($i*4+1),1);
					$res11=$this->hu2[$res1];
					$res12=$this->hu2[$res2];
					$res14=$res11*64+$res12;
					$res.=" ".$res14;
				}
			}
		}
		return trim($res);
	}

	/**
	 * 字符解密
	 * @param  $str 需要解密的字符
	 * @return string
	 */
	function decode($str)
	{
		$str=$this->discode($str);
		$a=explode(" ",$str);
		$res="";
		$huyang=new carry(7,35);
		$huyang1=new carry(10,8);
		for($i=0;$i<count($a);$i++){
			if($i==(count($a)-1)){
				$res.=$huyang->get($huyang1->get($a[$i]));
			}
			else{
				$b=$huyang->get($huyang1->get($a[$i]));
				if(strlen($b)==0){
					$res.="000";
				}
				elseif(strlen($b)==1){
					$res.="00".$b;
				}
				elseif(strlen($b)==2){
					$res.="0".$b;
				}
				else{
					$res.=$b;
				}
			}
		}
		return $this->getcode($res);
	}
}
?>